//
// Created by Soar Qin on 2017/8/18.
// Copyright (c) 2017 Soar Qin. All rights reserved.
//

#include "common.hh"
#include "core/async/loop.hh"

#include "core/async/udp_endpoint.hh"
#include "core/async/ip_addr.hh"

#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <netinet/in.h>
#endif

class TestUDP: public core::async::UDPEndpoint {
public:
    using core::async::UDPEndpoint::UDPEndpoint;

protected:
    void onRead(const void *buf, size_t size, const core::async::IPAddr &from) override {
        int slen;
        auto *saddr = from.getAddr(slen);
        printf("%zu %d\n", size, htons(from.isIPv6() ? ((struct sockaddr_in6*)saddr)->sin6_port : ((struct sockaddr_in*)saddr)->sin_port));
        close();
    }
    void onWritten() override {
        printf("written\n");
    }
    void onClosed() override {
        printf("closed\n");
    }
};

int main(int argc, char **argv) {
    core::async::Loop l;
    TestUDP u1(l), u2(l);
    u1.bind("127.0.0.1:1234");
    u2.bind("127.0.0.1:1235");
    u1.write("abcdef", 5, core::async::IPAddr("127.0.0.1:1235"));
    u2.write("abcdefg", 6, core::async::IPAddr("127.0.0.1:1234"));
    l.run();
    return 0;
}

/*
#include "core/async/http_req.hh"
#include "core/async/timer.hh"

class TestReq: public core::async::HttpReqSimple {
public:
    using core::async::HttpReqSimple::HttpReqSimple;

protected:
    void onFinished(const std::string& url) override {
        printf("%s returns:\n%s\n", url.c_str(), data_.c_str());
    }
};

class TestTimer: public core::async::Timer {
public:
    using core::async::Timer::Timer;

protected:
    void onTimer() override {
        printf("timer\n");
    }
};
int main(int argc, char **argv) {
    core::async::Loop l;
    TestReq h(l);
    TestTimer t(l);
    t.start(1000000ULL, 5000000ULL);
    h.get("https://www.baidu.com");
    l.run();
    return 0;
}
*/

/*
#include "core/async/tcp_listener.hh"
#include "core/async/tcp_endpoint.hh"
#include "core/async/timer.hh"

class TestEndpoint: public core::async::TCPEndpoint {
public:
    using core::async::TCPEndpoint::TCPEndpoint;

protected:
    void onRead() override {
        writeTo(this);
    }
};

class TestListener: public core::async::TCPListener {
public:
    using core::async::TCPListener::TCPListener;

protected:
    bool onAccept(int fd) override {
        auto *ios = new TestEndpoint(loop_);
        if (!ios->bind(fd)) {
            return false;
        }
        ios->setDeleteOnClose();
        return true;
    }
};

class TestConnector: public core::async::TCPEndpoint {
public:
    using core::async::TCPEndpoint::TCPEndpoint;
    void onRead() override {
        char v[6];
        size_t count = read(v, 5);
        v[count] = 0;
        fprintf(stdout, "%s\n", v);
    }

protected:
    void onConnected() override {
        write("abcdef", 5);
    }
};

int main(int argc, char **argv) {
    core::async::Loop l;
    TestListener listener(l);
    if (!listener.listen(":1234")) {
        fprintf(stderr, "Unable to listen at :1234\n");
        return 0;
    }
    TestConnector ios(l);
    if (!ios.connect("127.0.0.1:1234")) {
        fprintf(stderr, "Unable to connect to 127.0.0.1:1234\n");
        return 0;
    }
    l.run();
    return 0;
}
*/
